package com.useful.web.config;

import com.useful.web.advice.GlobalExceptionAdvice;
import com.useful.web.advice.GlobalResponseAdvice;
import feign.RequestInterceptor;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.Optional;

/**
 * @author : wenchao.long
 * @date : Created in 2021/9/19 10:47 周日
 * @description :
 */
@Configuration
@RequiredArgsConstructor
public class GlobalDefaultConfiguration implements WebMvcConfigurer {

    @Bean
    public GlobalExceptionAdvice exceptionAdvice() {
        return new GlobalExceptionAdvice();
    }

    @Bean
    public GlobalResponseAdvice responseAdvice() {
        return new GlobalResponseAdvice();
    }

    /**
     * 让DispatcherServlet向子线程传递RequestContext
     *
     * @param servlet servlet
     * @return bean
     */
    @Bean
    @ConditionalOnBean({DispatcherServlet.class})
    public ServletRegistrationBean<DispatcherServlet> dispatcherServletRegistration(DispatcherServlet servlet) {
        servlet.setThreadContextInheritable(true);
        return new ServletRegistrationBean<>(servlet, "/**");
    }

    /**
     * 在进行feign调用时 会出现header丢失
     * 覆写拦截器 在feign发送请求前去取出原来的header并转发
     *
     * @return 拦截器
     */
    @Bean
    public RequestInterceptor requestInterceptor() {
        return template -> {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            Optional.ofNullable(attributes)
                    .ifPresent(attribute -> {
                        HttpServletRequest request = attribute.getRequest();
                        Enumeration<String> headerNames = request.getHeaderNames();
                        Optional.ofNullable(headerNames)
                                .ifPresent(headerName -> {
                                    while (headerName.hasMoreElements()) {
                                        String name = headerName.nextElement();
                                        String header = request.getHeader(name);
                                        template.header(name, header);
                                    }
                                });
                    });
        };
    }
}
